/**************************************************************/
/*  This file is licensed from, and is a trade secret of:     */
/*                                                            */
/*    Mercury Computer Systems, Incorporated                  */
/*    199 Riverneck Road                                      */
/*    Chelmsford, Massachusetts 01824-2820                    */
/*    United States of America                                */
/*    Telephone + 1 978 256-1300                              */
/*                                                            */
/*  Refer to your Software License Agreement for provisions   */
/*  on use, duplication, or disclosure.                       */
/*  US. Government users and prime contractors are also       */
/*  governed by the following Data Rights Notice:             */
/*  Use, duplication or disclosure by the US. Government is   */
/*  subject to the provisions set forth in FAR 52.227-14 for  */
/*  restricted rights or other agency data rights provisions  */
/*  on commercial software and documentation, as applicable.  */
/*                                                            */
/*  This file: (a) was developed at private expense, and no   */
/*  part was developed with government funds, (b) is a        */
/*  trade secret of Mercury Computer Systems, Inc. for the    */
/*  purposes of the Freedom of Information Act, (c) is        */
/*  "commercial computer software" subject to limited         */
/*  utilization as provided in the above noted Software       */
/*  License Agreement and (d) is in all respects data         */
/*  belonging exclusively to Mercury Computer Systems, Inc..  */
/*                                                            */
/**************************************************************/

/******************************************************************/
/* Copyright (c) 1999-2003, Mercury Computer Systems, Inc.,       */
/* Chelmsford MA.,and all third party embedded software sources.  */
/* All rights reserved under the Copyright laws of US. and        */
/* international treaties.                                        */
/*                                                                */
/* Patent Pending                                                 */
/******************************************************************/


//$COPYRIGHT_END

#include <iostream>
#include <assert.h>
#include <tao/corba.h>

#include "BaseAssemblyController.h"
#include "SCA_Types.h"

/* 
 * ----------------------------------------------------------------------
 * PropertyMapping methods.
 * ----------------------------------------------------------------------
 */

BaseAssemblyController::
PropertyMapping::PropertyMapping (const char * assembly_property_name, 
				  const char * component_id,
				  const char * component_prop_name)
  : m_assembly_propname (assembly_property_name),
    m_initial_set (false)
{
  m_targets.resize(1);
  PropertyMapTarget * target = new PropertyMapTarget (component_id,
						      component_prop_name);
  m_targets[0] = target;
} // End of PropertyMapping()

BaseAssemblyController::
PropertyMapping::~PropertyMapping()
{
  vector_ptrs_cleanup (m_targets);
} // End of PropertyMapping()

bool 
BaseAssemblyController::
PropertyMapping::PropertyTypeMatch (const CF::DataType & cf_prop)
{
  assert (m_targets.size());

  // Until the properties are initially set, we can't perform the type match.
  if (!m_initial_set) {
    return true;
  }

  CORBA::TypeCode_var in_typecode = cf_prop.value.type();
  CORBA::TypeCode_var my_typecode = m_targets[0]->m_cf_property->value.type();
  return (in_typecode->kind() == my_typecode->kind());
} // End of PropertyMapping::PropertyTypeMatch()

void 
BaseAssemblyController::
PropertyMapping::SetPropValues (const CF::DataType & cf_prop_in)
{
  std::string in_prop_name(cf_prop_in.id);
  assert (in_prop_name == m_assembly_propname);

  // Set each target
  std::vector<PropertyMapTarget *>::iterator pm_i;
  for (pm_i=m_targets.begin(); pm_i!=m_targets.end(); pm_i++) {
    PropertyMapTarget & t = **pm_i;
    assert(!CORBA::is_nil(t.m_res_ref));
    t.m_cf_property->value = cf_prop_in.value;

#ifdef VERBOSE
    cout << "BaseAssemblyController: Setting property value for component \"" 
	 << t.m_res_ref->identifier ()
	 << "\", id \""
	 << t.m_cf_properties[0].id
	 << "\"."
	 << endl;
#endif
    t.m_res_ref->configure (t.m_cf_properties);
  }

  m_initial_set = true;
} // End of PropertyMapping::SetPropValues()

void 
BaseAssemblyController::
PropertyMapping::GetPropValue (CF::DataType &cf_prop,
			       unsigned long index)
{
  std::string in_prop_name (cf_prop.id);
  assert(in_prop_name == m_assembly_propname);

  // Get property value from first target
  PropertyMapTarget &t = *(m_targets[index]);
  assert (!CORBA::is_nil(t.m_res_ref));

  t.m_res_ref->query (t.m_cf_properties);
  cf_prop.value = t.m_cf_property->value;
} // End of PropertyMapping::GetPropValue()


void
BaseAssemblyController::
PropertyMapping::AddPropertyTarget (const char *component_id,
                                    const char *component_prop_name)
{
  unsigned long num_current_targets = m_targets.size();

  m_targets.resize (num_current_targets + 1); // increase size by 1
  PropertyMapTarget *target = new PropertyMapTarget (component_id,
						     component_prop_name);
  m_targets[num_current_targets] = target;
} // End of PropertyMapping::AddPropertyTarget()

/*
 * ----------------------------------------------------------------------
 * PropertyMapTarget methods.
 * ----------------------------------------------------------------------
 */

BaseAssemblyController::
PropertyMapTarget::PropertyMapTarget (const char * component_id, 
				      const char * prop_name)
  : m_component_id (component_id)
{
  m_cf_properties.length(1);
  m_cf_properties[0].id = CORBA::string_dup (prop_name);
  m_cf_property = &m_cf_properties[0];
}

BaseAssemblyController::
PropertyMapTarget::~PropertyMapTarget()
{
  m_res_ref = CF::Resource::_nil();
}

/*
 * ----------------------------------------------------------------------
 * ComponentPropertyQueue
 * ----------------------------------------------------------------------
 */

// Queues up the properties via components.
BaseAssemblyController::
ComponentPropertyQueue::~ComponentPropertyQueue ()
{
  unsigned int ii, num_cfg_components = m_component_props.size ();

  for (ii=0; ii<num_cfg_components; ++ii) {
    m_component_props[ii]->m_res_ref = CF::Resource::_nil();
    delete m_component_props[ii];
  }
} // End of ~ComponentPropertyQueue()

// Queue up the properties via components
void 
BaseAssemblyController::
ComponentPropertyQueue::QueuePropValues (PropertyMapping & prop_map, 
					 const CF::DataType & cfgProp)
{
  unsigned int ii;
  int component_prop_index;

  /*
   * Process all of the property target mappings for a given assembly
   * Controller property mapping.
   */

  for (ii=0; ii<prop_map.m_targets.size(); ++ii) {
    /*
     * Search through existing component property queues to see if one exists
     * for our property's component.
     */

    PropertyMapTarget & my_prop_map_target = *(prop_map.m_targets[ii]);

    // Determine the config prop array for this config property.
    component_prop_index = 
      GetPropertyCompIndex (my_prop_map_target.m_component_id.c_str());

    /*
     * If we don't already have a config prop vector for the component
     * associated with this property, add a new one.
     */

    if (component_prop_index < 0) {
      // Add a new property array.
      unsigned int current_array_size = m_component_props.size();
      m_component_props.resize(current_array_size + 1);
      m_component_props[current_array_size] = new struct component_properties();

      // Initialize struct values
      struct component_properties & my_component_property_struct = 
	*(m_component_props[current_array_size]);

      my_component_property_struct.m_component_id = 
	my_prop_map_target.m_component_id;

      my_component_property_struct.m_res_ref = 
	CF::Resource::_duplicate(my_prop_map_target.m_res_ref);

      // Add this property to the list.
      my_component_property_struct.m_comp_cf_properties.length (1);
      my_component_property_struct.m_comp_cf_properties[0].id = 
	my_prop_map_target.m_cf_property->id;
      my_component_property_struct.m_comp_cf_properties[0].value = 
	cfgProp.value;

      m_component_index_mappings[m_component_props[current_array_size]->m_component_id] = 
	current_array_size;
    }
    else {
      // Add our property to the existing property array.
      struct component_properties & my_comp_prop_struct = 
	*(m_component_props[component_prop_index]);

      unsigned int num_current_cfg_props = 
	my_comp_prop_struct.m_comp_cf_properties.length();

      my_comp_prop_struct.m_comp_cf_properties.length (num_current_cfg_props+1);
      my_comp_prop_struct.m_comp_cf_properties[num_current_cfg_props].id = 
	my_prop_map_target.m_cf_property->id;
      my_comp_prop_struct.m_comp_cf_properties[num_current_cfg_props].value = 
	cfgProp.value;
    }
  } // End of for (ii=0; ii<prop_map.m_targets.size(); ++ii)
} // End of QueuePropValues(PropertyMapping &prop_map, const CF::DataType &cfgProp)

// Configure each of the components in the queues
void 
BaseAssemblyController::
ComponentPropertyQueue::ConfigureComponentProps ()
{
  unsigned long ii, num_cfg_components;
  num_cfg_components = m_component_props.size();

  for (ii=0; ii<num_cfg_components; ++ii) {
    struct component_properties &my_prop_data = *(m_component_props[ii]);
    assert(!CORBA::is_nil(my_prop_data.m_res_ref));
    my_prop_data.m_res_ref->configure(my_prop_data.m_comp_cf_properties);
  }
} // End of ConfigureComponentProps()

int 
BaseAssemblyController::
ComponentPropertyQueue::GetPropertyCompIndex (const char *property_name)
{
  map<string, int>::iterator m_i;
  string temp_name(property_name);

  m_i = m_component_index_mappings.find(temp_name);

  if (m_i == m_component_index_mappings.end()) {
    return -1;
  }

  return m_i->second;
} // End of GetPropertyIndex()
